home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C011.ZIP / LDIR.C < prev    next >
Text File  |  1990-01-19  |  11KB  |  432 lines

  1. /********************************************************************
  2.  * C Users Group (U.K) C Source Code Library File CUGLIB.011        *
  3.  * Inquiries to: M. Houston, 36 Whetstone Clo. Farquhar Rd.         *
  4.  * Edgbaston, Birmingham B15 2QN ENGLAND                *
  5.  ********************************************************************
  6.  * File name: ldir.c
  7.  * Program name: ldir
  8.  * Source of file: The Public Domain Software Library.
  9.  * Purpose: library directory display program
  10.  * Changes: <who what when & why major changes have been made>      
  11.  ********************************************************************/
  12.  
  13. /*    LDIR     Library Directory display program */
  14.  
  15. #define    VERSION        3 
  16. #define    REVISION    0
  17. #define MOD_DATE    "84-02-29"
  18.  
  19. /*
  20. Legal Notices:
  21.     Copyright (c) 1982, 1983 by Gary P. Novosielski.
  22.     All rights reserved.
  23.  
  24.     Permission is hereby granted for noncommercial use.
  25.     Use or duplication of this or any derivative work for
  26.     commercial advantage without prior written consent
  27.     of the author is prohibited.
  28.  
  29. LIFO Revision Summary:
  30.     3.00    84-29-84    Revised for use on IBM-PC running
  31.                 MS-DOS. Compiler = Lattice 'c'
  32.                 (Pete Mack)
  33.     2.20    83-10-13    Changed Kb size calculation to
  34.                 round upward.  Added max drive
  35.                 validation.  Moved copyright
  36.                 display to help section.
  37.     2.11    83-03-21    BDS 1.5 support.
  38.                 Size display in Kb.
  39.     2.10    82-12-09    Size display in sectors.
  40.     2.00    82-11-20    [Not released]
  41.     1.00    82-11-14    Initial source release
  42.         Gary P. Novosielski
  43.  
  44. Program Description:
  45.     This program is intended for use on RCPM systems to
  46.     allow callers to see the contents of the directories
  47.     of .LBR files on the system.  You probably won't need
  48.     it on your home system, since the -L function of LU.COM
  49.     provides this ability.  Since LU is not active on
  50.     remote systems, a program like this is necessary
  51.     to allow you to see member names in a library without
  52.     your having to download the library first.
  53. */
  54.  
  55. #include "stdio.h"
  56. #include "ctype.h"
  57.  
  58. /* Pseudo typedef's */
  59. #define FLAG        char
  60.  
  61. /* Number of displayed entries */
  62. #define NWIDE    4
  63.  
  64. /*         EXTERNALS */
  65. FILE   *lbrfile, *fopen();             /* fd for library file    */
  66. char lbrname[20];
  67.  
  68. #define FROM_START    0
  69.  
  70. FLAG lbropen;
  71. int  entries, freeent;
  72.  
  73. /* Entry Size */
  74. #define ESIZE        32
  75.  
  76. /* Entries per sector */
  77. #define EPS        (SECSIZ / ESIZE)
  78.  
  79. /* Structure of a directory entry */
  80. struct direntry
  81. {
  82.     char status;    /* Possible values */
  83. #define  ACTIVE            0x00
  84. #define  KILLED            0xFE
  85. #define     VIRGIN            0xFF
  86.     char id[8+3];     /* filename.ext */
  87.     unsigned indx;    /* Pointer to first sector */
  88.     unsigned size;    /* Size of member in sectors */
  89.     unsigned crc;    /* CRC check word */
  90.     /* Future expansion space */
  91. #define EXPSIZ            14
  92.     char expand[EXPSIZ];
  93. }
  94. *directory, *curentry;    /* two pointers to such a beast */
  95.  
  96. typedef struct direntry dirtype;
  97.  
  98. char sopt;        /* size option: S, N, or K */
  99. char *drmsg;        /* Max drive letter allowed */
  100.  
  101. /*        END OF EXTERNALS */
  102. #define SECSIZ    128
  103. #define OK    0
  104.  
  105. /************************************************
  106.  main
  107. *************************************************/
  108.  
  109. main (argc,argv)
  110. unsigned  argc;
  111. char *argv[];
  112. {
  113.     cprintf(
  114.       "Library DIRectory   Ver:%d.%02d   %s\n\r%s\n\r",
  115.       VERSION,REVISION,MOD_DATE,
  116.       "Press CTRL-S to pause; CTRL-C to cancel"
  117.       );
  118.  
  119.  
  120.     /*
  121.     The FIRST character of the following message is actually
  122.     used in the test for the maximum legal drive.  This will
  123.     allow sites which do not support a C compiler to easily
  124.     find and patch this value in the object code.
  125.     */
  126.     drmsg = "P: is highest valid drive";
  127.  
  128.  
  129.     /* Initialize flags */
  130.     sopt = 'K';            /* Default option setting */
  131.     lbropen = FALSE;        /* No library open */
  132.     directory = NULL;        /* No directory in memory */
  133.  
  134.  
  135.     if (argc < 2)        /* No command line arguments */
  136.     {
  137.     cputs("\n\rCopyright (c) 1982, 1983 by Gary P. Novosielski");
  138.     cputs("\n\r\nCorrect syntax is:");
  139.     cputs("\n\rLDIR [<option>] name1 [[<option>] [name2...[nameN]]]");
  140.     cputs("\n\r\nWhere:\tname1 through");
  141.     cputs("\n\r\tnameN\tare library names; default type: .LBR");
  142.     cputs("\n\rOptions:\n\r\t-n\tonly show names of members.");
  143.     cputs("\n\r\t-s\talso show size in sectors.");
  144.     cputs("\n\r\t-k\tlike -s, but size in Kbytes. (default)");
  145.     cputs("\n\rOption flags stay in effect for subsequent names.");
  146.     cputs("\n\rAmbiguous names are not permitted.");
  147.  
  148.  
  149.  
  150.     }
  151.     else
  152.     /* Process command line arguments */
  153.     while(--argc)
  154.     {
  155.         if (**(++argv) == '-')
  156.         procopt(*argv);
  157.         else if (!namel(*argv))
  158.         dirlist();
  159.         else
  160.         cprintf("\n\r%s not found on disk.\n\r",lbrname);
  161.  
  162.     }
  163.     /* End of command line.  Clean up and exit */
  164. }
  165. /* End of main function */
  166.  
  167. /************************************************
  168.  Open *name as the current library
  169. *************************************************/
  170.  
  171. namel(name)
  172. char *name;
  173. {
  174.     if (lbropen && close(lbrfile) == ERROR)
  175.     abend("\n\rCan't close library: %s",lbrname);
  176.     lbropen = FALSE;
  177.     if (isambig(name) || indexc(name,' ') != ERROR)
  178.     abend("\n\rBad library name: %s",name);
  179.     if (name[1] == ':' && *name > *drmsg)
  180.     abend("\n\r%s",drmsg);
  181.     strcpy(lbrname,name);
  182.     if (indexc(name,'.') == ERROR)
  183.     strcat(lbrname,".LBR");
  184.     if ((lbrfile = fopen(lbrname,"r")) != NULL)
  185.     {
  186.     cprintf("\n\rLibrary: %s has ",lbrname);
  187.     readdir();
  188.     }
  189.     else
  190.     return ERROR;
  191.     lbropen = TRUE;
  192.     cprintf ("%d entries, %d free:\n\r",entries,freeent);
  193.     return OK;
  194. }
  195.  
  196. /************************************************
  197.    Return flag saying if the requested number of memory bytes
  198.    are available.  Try to make them available if possible.
  199. *************************************************/
  200.  
  201. FLAG avail(request)
  202. unsigned request;    /* in bytes */
  203. {
  204.     char *ptr;
  205.     unsigned  *curavail, temp;
  206.     temp = 0;
  207.  
  208.     curavail = &temp;    /* Pseudo-static kluge */
  209.  
  210.     if(request < *curavail)
  211.     return TRUE;
  212.     if ((ptr = (char *) sbrk(++request - *curavail)) == ERROR)
  213.     return FALSE;
  214.  
  215.     /* If this is the first success, initialize pointer */
  216.     if (directory == NULL)
  217.     directory =  (dirtype *) ptr;
  218.  
  219.     *curavail = request; /* Modify static for next call */
  220.     return TRUE;
  221. }
  222.  
  223. /************************************************
  224. /* Read the directory into memory */
  225. *************************************************/
  226.  
  227. readdir()
  228. {
  229.     if (!avail(SECSIZ))
  230.     memerr();
  231.     fseek(lbrfile, 0, FROM_START);
  232.  
  233.     if (
  234.       fread(directory,128,1,lbrfile) != 1
  235.       || entcmp(directory,"\0           ")
  236.       || directory->indx
  237.       || !directory->size
  238.       )
  239.     abend("no directory");
  240.  
  241.     if (directory->size > 1)
  242.     {
  243.     if (!avail(SECSIZ * directory->size))
  244.         memerr();
  245.     if (fread(directory+EPS,128, directory->size - 1,lbrfile)
  246.       != directory->size - 1)
  247.         abend("a bad directory");
  248.     }
  249.  
  250.     freeent = entries = EPS * directory->size;
  251.  
  252.     for(
  253.       curentry = directory;
  254.       curentry->status != VIRGIN && freeent;
  255.       ++curentry
  256.       )
  257.     --freeent;
  258. }
  259.  
  260. /************************************************
  261.  memory error
  262. *************************************************/
  263.  
  264. memerr()
  265. {
  266.     abend("an absurdly huge directory");
  267. }
  268.  
  269. /************************************************
  270.   Search string *s for character c.  Return offset 
  271. *************************************************/
  272.  
  273. int indexc(s, c)
  274. char *s, c;
  275. {
  276.     int i;
  277.     for (i = 0; *s; i++) 
  278.     if(*s++ == c)
  279.         return i;
  280.     return ERROR;
  281. }
  282.  
  283. /************************************************
  284.   Return TRUE if s contains asterisk(s) or question(s)
  285. *************************************************/
  286.  
  287. isambig(s)
  288. char *s;
  289. {
  290.     if (indexc(s,'*') != ERROR || indexc(s,'?') != ERROR)
  291.     return TRUE;
  292.     return FALSE;
  293. }
  294.  
  295. /************************************************
  296.  Terminate program with error message 
  297. *************************************************/
  298.  
  299. abend(p1, p2, p3, p4)
  300. {
  301.     cprintf(p1, p2, p3, p4);
  302.     cputs("\n\r\nFor help, type LDIR alone.");
  303.     exit();
  304. }
  305.  
  306. /************************************************
  307.  compare string a to string b ignoring some bits of each
  308. *************************************************/
  309.  
  310. bitcmp(a, b, count, mask)
  311. char *a, *b, mask;
  312. int count;
  313. {
  314.     int r;
  315.     while(count--)
  316.     if (r = (*a++ & mask) - (*b++ & mask))
  317.         return r;
  318.     return 0;
  319. }
  320.  
  321. /************************************************
  322.  form a string in dst from a standard format name in src
  323. *************************************************/
  324.  
  325. formname(dst,src)
  326. char *dst, *src;
  327. {
  328.     int i,j;
  329.     j = 0;
  330.  
  331. /* Remove attributes first so compares will work */
  332.     for (i = 1; i < 12; i++)
  333.     src[i] &= 0x7F;
  334.     for (i = 1; i < 9; i++)
  335.     {
  336.     if (src[i] == ' ')
  337.         break;
  338.     dst[j++] = src[i];
  339.     }
  340.     if (src[9] != ' ')
  341.     dst[j++] = '.';
  342.     for (i = 9; i < 12; i++)
  343.     {
  344.     if (src[i] == ' ')
  345.         break;
  346.     dst[j++] = src[i];
  347.     }
  348.     dst[j] = '\0';
  349.     return dst;
  350. }
  351.  
  352. /************************************************
  353.    Compare two directory entries. Note that status is major
  354.    sort field.
  355. *************************************************/
  356.  
  357. entcmp(a,b)
  358. char *a, *b;
  359. {
  360.     int  i, r;
  361.  
  362.     for (i = (1+8+3); i--; a++, b++)
  363.     if ((r = *a - *b) && *b != '?')
  364.         return r;
  365.     return 0;
  366. }
  367.  
  368. /************************************************
  369.    List the directory of the current library, and return number
  370.    of free entries
  371. *************************************************/
  372.  
  373. dirlist()
  374. {
  375.     char name[20];
  376.     int  i;
  377.     unsigned del, act;
  378.  
  379.     curentry = directory;
  380.     for ((act = del = 0, i = entries - freeent); --i;)
  381.     {
  382.     if ((++curentry)->status == ACTIVE) 
  383.     {
  384.         if(!(act % NWIDE))  
  385.         cputs("\n\r");
  386.         formname(name, curentry);
  387.  
  388.         switch (sopt)
  389.         {
  390.         case 'S':    /* Size in sectors */
  391.         cprintf("%-12s%5ds ", name, curentry->size);
  392.         break;
  393.         case 'K':    /* Size in Kilobytes */
  394.         cprintf("%-12s%5dk ",name, (curentry->size+7)/8);
  395.         break;
  396.         case 'N':    /* Name only. More names per line */
  397.         cprintf("%-14s",name);
  398.         }
  399.         ++act;
  400.     }
  401.     else
  402.         ++del;
  403.     }
  404.     cprintf("\n\r Active entries: %u, Deleted: %u, Free: %u, Total: %u.\n\r",
  405.       ++act, del, freeent, entries);
  406.     return --act;
  407. }
  408.  
  409. /************************************************
  410.  Process option string (-xx)
  411. *************************************************/
  412.  
  413. procopt(s)
  414. char *s;
  415. {
  416.  
  417.     while(*(++s))
  418.     switch (*s)
  419.     {
  420.     case 'S':
  421.     case 'N':
  422.     case 'K':
  423.     case 's':
  424.     case 'n':
  425.     case 'k':
  426.         sopt = toupper(*s);
  427.         break;
  428.     default:
  429.         abend("'%c' is an invalid option",*s);
  430.     }
  431. }
  432.